{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(47, 3) <class 'numpy.ndarray'>\n",
      "(47, 1) <class 'numpy.ndarray'>\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "\n",
    "def normalize_feature(df):\n",
    "    return df.apply(lambda column: (column - column.mean()) / column.std())\n",
    "\n",
    "\n",
    "df = normalize_feature(pd.read_csv('data1.csv',\n",
    "                                   names=['square', 'bedrooms', 'price']))\n",
    "\n",
    "ones = pd.DataFrame({'ones': np.ones(len(df))})# ones是n行1列的数据框，表示x0恒为1\n",
    "df = pd.concat([ones, df], axis=1)  # 根据列合并数据\n",
    "\n",
    "X_data = np.array(df[df.columns[0:3]])\n",
    "y_data = np.array(df[df.columns[-1]]).reshape(len(df), 1)\n",
    "\n",
    "print(X_data.shape, type(X_data))\n",
    "print(y_data.shape, type(y_data))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 创建线性回归模型（数据流图）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "\n",
    "alpha = 0.01 # 学习率 alpha\n",
    "epoch = 500 # 训练全量数据集的轮数\n",
    "\n",
    "with tf.name_scope('input'):\n",
    "    # 输入 X，形状[47, 3]\n",
    "    X = tf.placeholder(tf.float32, X_data.shape, name='X')\n",
    "    # 输出 y，形状[47, 1]\n",
    "    y = tf.placeholder(tf.float32, y_data.shape, name='y')\n",
    "\n",
    "with tf.name_scope('hypothesis'):\n",
    "    # 权重变量 W，形状[3,1]\n",
    "    W = tf.get_variable(\"weights\",\n",
    "                        (X_data.shape[1], 1),\n",
    "                        initializer=tf.constant_initializer())\n",
    "    # 假设函数 h(x) = w0*x0+w1*x1+w2*x2, 其中x0恒为1\n",
    "    # 推理值 y_pred  形状[47,1]\n",
    "    y_pred = tf.matmul(X, W, name='y_pred')\n",
    "\n",
    "with tf.name_scope('loss'):\n",
    "    # 损失函数采用最小二乘法，y_pred - y 是形如[47, 1]的向量。\n",
    "    # tf.matmul(a,b,transpose_a=True) 表示：矩阵a的转置乘矩阵b，即 [1,47] X [47,1]\n",
    "    # 损失函数操作 loss\n",
    "    loss_op = 1 / (2 * len(X_data)) * tf.matmul((y_pred - y), (y_pred - y), transpose_a=True)\n",
    "with tf.name_scope('train'):\n",
    "    # 随机梯度下降优化器 opt\n",
    "    train_op = tf.train.GradientDescentOptimizer(learning_rate=alpha).minimize(loss_op)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 创建会话（运行环境）"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 100 \t Loss=0.1835 \t Model: y = 0.4909x1 + 0.1621x2 + -6.147e-10\n",
      "Epoch 200 \t Loss=0.1483 \t Model: y = 0.6678x1 + 0.1255x2 + 2.119e-10\n",
      "Epoch 300 \t Loss=0.1379 \t Model: y = 0.7522x1 + 0.07118x2 + 5.087e-10\n",
      "Epoch 400 \t Loss=0.1337 \t Model: y = 0.8004x1 + 0.02938x2 + 1.694e-09\n",
      "Epoch 500 \t Loss=0.132 \t Model: y = 0.8304x1 + 0.0008239x2 + 4.138e-09\n"
     ]
    }
   ],
   "source": [
    "with tf.Session() as sess:\n",
    "    # 初始化全局变量\n",
    "    sess.run(tf.global_variables_initializer())\n",
    "    # 创建FileWriter实例，并传入当前会话加载的数据流图\n",
    "    writer = tf.summary.FileWriter('./summary/linear-regression-1', sess.graph)\n",
    "    # 记录所有损失值\n",
    "    loss_data = []\n",
    "    # 开始训练模型\n",
    "    # 因为训练集较小，所以采用批梯度下降优化算法，每次都使用全量数据训练\n",
    "    for e in range(1, epoch + 1):\n",
    "        _, loss, w = sess.run([train_op, loss_op, W], feed_dict={X: X_data, y: y_data})\n",
    "        # 记录每一轮损失值变化情况\n",
    "        loss_data.append(float(loss))\n",
    "        if e % 100 == 0:\n",
    "            log_str = \"Epoch %d \\t Loss=%.4g \\t Model: y = %.4gx1 + %.4gx2 + %.4g\"\n",
    "            print(log_str % (e, loss, w[1], w[2], w[0]))\n",
    "\n",
    "# 关闭FileWriter的输出流\n",
    "writer.close()            "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 可视化损失值"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "500\n"
     ]
    }
   ],
   "source": [
    "print(len(loss_data))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "sns.set(context=\"notebook\", style=\"whitegrid\", palette=\"dark\")\n",
    "\n",
    "ax = sns.lineplot(x='epoch', y='loss', data=pd.DataFrame({'loss': loss_data, 'epoch': np.arange(epoch)}))\n",
    "ax.set_xlabel('epoch')\n",
    "ax.set_ylabel('loss')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
